import { useRef, useMemo, useState, useEffect, useCallback, type ChangeEvent } from 'react';
import { definePageConfig } from 'ice';
import { debounce } from 'lodash-es';
import { Space, message } from 'antd';
import { DiffEditor } from '@monaco-editor/react';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import Tour from '@/components/Tour';
import Upload from '@/components/Upload';
import Button from '@/components/Button';
import Loading from '@/components/Loading';
import Tooltip from '@/components/Tooltip';
import { useStateRef } from '@/common/hooks';
import { isDegrade } from '@/common/constant';
import { isTrue, rpxToPx, formatCSS, filterPxStyles, preventDefault } from '@/common/utils';

import styles from './index.module.scss';

/** 新手引导开关 */
let guider = false;
/** 编辑器 */
let monacoEditor;
/** 原始的编辑器 */
let originalEditor;
/** 修改后的编辑器 */
let modifiedEditor;
/** 默认缩放倍率 */
const defaultScale = 2;
/** 上次的缩放倍率 */
let preScale: string | number = defaultScale;
/** 错误信息 */
const errorMessage = '请输入正确的代码';

export default function Home() {
  // 编辑器初始化
  const [inited, setInited] = useState(false);
  // 需要复制的内容
  const [copyValue, setCopyValue] = useState('');
  // 新手引导开关
  const [tourOpen, setTourOpen] = useState(false);
  // 编辑器全屏
  const [fullscreen, setFullscreen] = useState(false);
  // 缩放倍率
  const [scale, setScale, scaleRef] = useStateRef<number | string>(defaultScale);

  /** 缩放提示词 */
  const scaleTip = useMemo(() => {
    const res = { title: '失焦才会保存' } as { title: string; color?: string };
    const isEmpty = scale === '';
    if (isEmpty || +scale < 1) {
      res.color = '#f14f4e';
      res.title = '缩放倍率不能小于1';
      if (isEmpty) res.title = '请输入正确的缩放倍率';
    }
    return res;
  }, [scale]);

  /** 保存按钮容器 */
  const saveContainerRef = useRef<HTMLDivElement>(null);
  /** 全屏按钮容器 */
  const fullscreenRef = useRef<HTMLDivElement>(null);
  /** 上传文件按钮容器 */
  const uploadRef = useRef<HTMLDivElement>(null);
  /** 缩放倍率容器 */
  const scaleContainerRef = useRef<HTMLDivElement>(null);
  /** 复制按钮容器 */
  const copyRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    // 检测本地是否有引导
    guider = !isTrue(localStorage.getItem('guider'));
    // 全局禁用右键
    document.addEventListener('contextmenu', preventDefault);
    // 监听全屏变化
    document.addEventListener('fullscreenchange', fullscreenChange);

    return () => {
      document.removeEventListener('contextmenu', preventDefault);
      document.removeEventListener('fullscreenchange', fullscreenChange);
    };
  }, []);

  /**
   * 处理全屏变化
   */
  const fullscreenChange = () => setFullscreen(Boolean(document.fullscreenElement));

  /**
   * 初始化编辑器
   */
  const initEditor = useCallback((editor, monaco) => {
    // 设置编辑器初始化完成
    setInited(true);
    // 设置编辑器
    monacoEditor = monaco;
    // 设置原始编辑器
    originalEditor = editor.getOriginalEditor();
    // 设置修改后的编辑器
    modifiedEditor = editor.getModifiedEditor();
    // 聚焦到修改后的编辑器
    if (!guider) modifiedEditor.focus();
  }, []);

  /**
   * 获取修改后的值
   */
  const getModifiedValue = useCallback(() => modifiedEditor?.getValue(), []);

  /**
   * 设置修改后的值
   */
  const setModifiedValue = useCallback(async (v: string) => {
    const css = await formatCSS(v);
    if (css) modifiedEditor.setValue(css);
  }, []);

  /**
   * 设置原始的值
   */
  const setOriginalValue = useCallback((v: string) => {
    setCopyValue(v === errorMessage ? '' : v);
    originalEditor.setValue(v);
  }, []);

  /**
   * 设置最后一行为空
   */
  const setLastLine = useCallback(() => {
    const model = modifiedEditor.getModel();
    const lastLine = model.getLineCount();
    const lastLineContent = model.getLineContent(lastLine);
    if (lastLineContent === '') return;
    modifiedEditor.pushUndoStop();
    const maxColumn = model.getLineMaxColumn(lastLine);
    model.pushEditOperations(
      [],
      [{ range: new monacoEditor.Range(lastLine, maxColumn, lastLine, maxColumn), text: '\n' }],
      () => null,
    );
    modifiedEditor.pushUndoStop();
  }, []);

  /**
   * 设置最后一行为空
   */
  const fit = useCallback(async () => {
    const value = getModifiedValue();
    if (value.trim()) {
      let fitCSS: void | string = '';
      const css = await formatCSS(value);
      if (css) {
        /** 将 `rpx` 转 `px` 后的值 */
        const pxValue = rpxToPx(css, +scaleRef.current);
        fitCSS = await formatCSS(`@media(min-width:480px){${isDegrade ? pxValue : filterPxStyles(pxValue)}}`);
        setLastLine();
      }
      setOriginalValue(fitCSS || errorMessage);
    } else {
      setOriginalValue('');
    }
  }, []);

  /**
   * 处理粘贴
   */
  const paste = useCallback(() => {
    const value = getModifiedValue();
    if (value.trim()) setModifiedValue(value);
  }, []);

  /**
   * 在编辑器挂载时调用
   */
  const onMount = useCallback((editor, monaco) => {
    // 初始化编辑器
    initEditor(editor, monaco);
    // 监听修改后的编辑器内容
    modifiedEditor.onDidChangeModelContent(debounce(() => fit(), 300));
    // 监听粘贴
    modifiedEditor.onDidPaste(debounce(paste, 300, { leading: true }));
    // 检测本地是否有引导
    if (guider) setTimeout(() => setTourOpen(true), 0);
  }, []);

  /**
   * 复制回调
   */
  const handleCopy = useCallback((value: string, success: boolean) => {
    if (value) success ? message.success('复制成功') : message.error('复制失败');
  }, []);

  /**
   * 处理全屏
   */
  const handleFullscreen = useCallback(() => {
    fullscreen ? document.exitFullscreen() : document.documentElement.requestFullscreen();
  }, [fullscreen]);

  /**
   * 缩放倍率改变
   */
  const handleBlur = useCallback(() => {
    const value = scaleRef.current;
    // 如果没有变化就不处理
    if (value === preScale) return;
    // 如果不是有效值就重置
    if (+value < 1) {
      setScale(preScale);
      return;
    }
    fit();
    preScale = value;
  }, []);

  /**
   * 缩放倍率改变
   */
  const handleChange = useCallback((e: ChangeEvent<HTMLInputElement>) => setScale(e.target.value), []);

  return (
    <>
      <div className={styles.home}>
        <div x-if={inited} className={styles.titlebar}>
          <div className={styles.left}>
            <div className={styles.tips}>转换后的样式：</div>
            <Space size={10}>
              {/* 保存按钮预留位 */}
              <div ref={saveContainerRef} />
              <CopyToClipboard text={copyValue} onCopy={handleCopy}>
                <Button ref={copyRef} disable={!copyValue} reason="转换后的样式不正确">
                  复制
                </Button>
              </CopyToClipboard>
            </Space>
          </div>
          <div className={styles.right}>
            <div className={styles.tips}>待转换的样式：</div>
            <Space size={10}>
              <div ref={scaleContainerRef}>
                缩放倍率：
                <Tooltip trigger="focus" color={scaleTip.color} title={scaleTip.title}>
                  <input
                    className={styles.scale}
                    type="number"
                    value={scale}
                    onBlur={handleBlur}
                    onChange={handleChange}
                  />
                </Tooltip>
              </div>
              <Upload
                ref={uploadRef}
                saveContainer={saveContainerRef}
                originalValue={copyValue}
                modifiedValue={getModifiedValue()}
                onChange={setModifiedValue}
              />
              <Button ref={fullscreenRef} onClick={handleFullscreen}>
                {fullscreen ? '退出全屏' : '进入全屏'}
              </Button>
            </Space>
          </div>
        </div>
        <DiffEditor
          width="100vw"
          height="calc(100vh - 35px)"
          theme="vs-dark"
          language="scss"
          loading={<Loading />}
          options={{
            tabSize: 2,
            fontSize: 13,
            wordWrap: 'on',
            contextmenu: false,
            automaticLayout: true,
            smoothScrolling: true,
            renderSideBySide: true,
            hover: { enabled: true },
            scrollBeyondLastLine: false,
            enableSplitViewResizing: false,
          }}
          onMount={onMount}
        />
      </div>

      <Tour
        x-if={inited && tourOpen}
        open
        onClose={() => {
          setTourOpen(false);
          modifiedEditor.focus();
          localStorage.setItem('guider', 'true');
        }}
        steps={[
          {
            desc: '在这里输入需要转换的样式',
            placement: 'left',
            target: document.querySelectorAll('.editor-scrollable')[1],
          },
          {
            desc: '转换完成后会在这里显示',
            placement: 'right',
            target: document.querySelectorAll('.editor-scrollable')[0],
          },
          {
            desc: '想要编辑器全屏的话，可以点这里试试，全屏更清晰',
            placement: 'bottom',
            target: fullscreenRef.current,
          },
          {
            desc: '这里可以解析文件，也支持直接将文件拖入到页面中，Chrome 支持一键写入到文件',
            placement: 'bottom',
            target: uploadRef.current,
          },
          {
            desc: '在这里输入自己需要的缩放倍率',
            placement: 'bottom',
            target: scaleContainerRef.current,
          },
          {
            desc: '可以一键复制转换后的样式，如果样式不正确，则无法复制',
            placement: 'bottom',
            target: copyRef.current,
          },
        ]}
      />
    </>
  );
}

export const pageConfig = definePageConfig(() => ({ title: '宽屏设备样式转换工具' }));
